﻿using NovoSerDes.Funcs;
using NovoSerDesEva;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace NovoSerDes
{
    [Serializable]
    public partial class Config : UIPage
    {
        private List<SerDesComm> serDesCommList = null;
        private Dictionary<string,UISwitch> comboxToSwitch = new Dictionary<string,UISwitch>();
        private Dictionary<UIComboBox, UIComboBox> DevToAddr = new Dictionary<UIComboBox, UIComboBox>();
        private Dictionary<UISwitch,UIComboBox> SwithToAddr = new Dictionary<UISwitch, UIComboBox>();
        private AddressMeditor mediatorA;
        private AddressMeditor mediatorB;
        private AddressMeditor mediatorC;
        private AddressMeditor mediatorD;
        private AddressMeditor mediatorDes;
        private USBDeviceMeditor usbDeviceMeditorA;
        private USBDeviceMeditor usbDeviceMeditorB;
        private USBDeviceMeditor usbDeviceMeditorC;
        private USBDeviceMeditor usbDeviceMeditorD;
        private USBDeviceMeditor usbDeviceMeditorDes;
        public Config()
        {
            InitializeComponent();        
            serDesCommList = MainForm.GetSerDesCommList();
            UpdataComboxData();
            InitDictional();
            this.combox_addA.SelectedIndex = 0;
            this.combox_addB.SelectedIndex = 0;
            this.combox_addC.SelectedIndex = 0;
            this.combox_addD.SelectedIndex = 0;
            this.combox_addDes.SelectedIndex = 0;
            this.combox_serA.SelectedIndex = 0;
            this.combox_serB.SelectedIndex = 0;
            this.combox_serC.SelectedIndex = 0;
            this.combox_serD.SelectedIndex = 0;
            this.combox_des.SelectedIndex = 0;
            this.combox_IICModeA.SelectedIndex = 2;
            this.combox_IICModeB.SelectedIndex = 2;
            this.combox_IICModeC.SelectedIndex = 2;
            this.combox_IICModeD.SelectedIndex = 2;
            this.combox_IICModeDes.SelectedIndex = 2;


            if (combox_devA.Items.Count > 0)
            {
                this.combox_devA.SelectedIndex = 0;
            }
            if (combox_devB.Items.Count > 0)
            {
                this.combox_devB.SelectedIndex = 0;
            }
            if (combox_devC.Items.Count > 0)
            {
                this.combox_devC.SelectedIndex = 0;
            }
            if (combox_devD.Items.Count > 0)
            {
                this.combox_devD.SelectedIndex = 0;
            }
            if (combox_devDes.Items.Count > 0)
            {
                this.combox_devDes.SelectedIndex = 0;
            }
        }

        private void InitDictional()
        {
            comboxToSwitch[this.combox_devA.Name] = this.uiSwitchA;
            comboxToSwitch[this.combox_devB.Name] = this.uiSwitchB;
            comboxToSwitch[this.combox_devC.Name] = this.uiSwitchC;
            comboxToSwitch[this.combox_devD.Name] = this.uiSwitchD;
            comboxToSwitch[this.combox_devDes.Name] = this.uiSwitchDes;

            DevToAddr[combox_devA] = combox_addA;
            DevToAddr[combox_devB] = combox_addB;
            DevToAddr[combox_devC] = combox_addC;
            DevToAddr[combox_devD] = combox_addD;
            DevToAddr[combox_devDes] = combox_addDes;

            SwithToAddr[this.uiSwitchA] = combox_addA;
            SwithToAddr[this.uiSwitchB] = combox_addB;
            SwithToAddr[this.uiSwitchC] = combox_addC;
            SwithToAddr[this.uiSwitchD] = combox_addD;
            SwithToAddr[this.uiSwitchDes] = combox_addDes;

        }
        public void UpdataComboxData()
        {
            serDesCommList = MainForm.GetSerDesCommList();
            int indexA = combox_devA.SelectedIndex;
            int indexB = combox_devB.SelectedIndex;
            int indexC = combox_devC.SelectedIndex;
            int indexD = combox_devD.SelectedIndex;
            int indexDes = combox_devDes.SelectedIndex;
            this.combox_devA.Items.Clear();
            this.combox_devB.Items.Clear();
            this.combox_devC.Items.Clear();
            this.combox_devD.Items.Clear();
            this.combox_devDes.Items.Clear();            
            for (int i = 0; i < serDesCommList.Count; ++i)
            {
                this.combox_devA.Items.Add(String.Format("{0}({1})", serDesCommList[i].GetDevName(), i));
                this.combox_devB.Items.Add(String.Format("{0}({1})", serDesCommList[i].GetDevName(), i));
                this.combox_devC.Items.Add(String.Format("{0}({1})", serDesCommList[i].GetDevName(), i));
                this.combox_devD.Items.Add(String.Format("{0}({1})", serDesCommList[i].GetDevName(), i));
                this.combox_devDes.Items.Add(String.Format("{0}({1})", serDesCommList[i].GetDevName(), i));
            }
            combox_devA.SelectedIndex = indexA;
            combox_devB.SelectedIndex = indexB;
            combox_devC.SelectedIndex = indexC;
            combox_devD.SelectedIndex = indexD;
            combox_devDes.SelectedIndex = indexDes;
        }

        public delegate void MyEventHandler(object sender, bool value);
        public event MyEventHandler AddPageClicked;
        private void uiSwitch1_ValueChanged(object sender, bool value)
        {     
            this.AddPageClicked?.Invoke(sender, value);
            this.combox_add_selectedIndexChanged(SwithToAddr[(UISwitch)sender], null);//设置地址
        }

        private void panelA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            Panel panel = (Panel)sender;
            switch (panel.Name)
            {
                case "panelA":
                    ControlPaint.DrawBorder(e.Graphics, panelA.ClientRectangle, System.Drawing.Color.Red, ButtonBorderStyle.Solid);
                    break;
                case "panelB":
                    ControlPaint.DrawBorder(e.Graphics, panelB.ClientRectangle, System.Drawing.Color.Green, ButtonBorderStyle.Solid);
                    break;
                case "panelC":
                    ControlPaint.DrawBorder(e.Graphics, panelC.ClientRectangle, Color.FromArgb(80, 160, 255), ButtonBorderStyle.Solid);
                    break;
                case "panelD":
                    ControlPaint.DrawBorder(e.Graphics, panelD.ClientRectangle, System.Drawing.Color.Orange, ButtonBorderStyle.Solid);
                    break;
                default:
                    break;
            }
            
        }

        public event EventHandler ComboxDataChanged;
        private async void combox_dev_SelectedIndexChanged(object sender, EventArgs e)
        {           
            ComboxDataChanged?.Invoke(sender, EventArgs.Empty);
            
            ////reload when devAdd is changed
            //uiSwitch1_ValueChanged(comboxToSwitch[((UIComboBox)sender).Name], false);
            //comboxToSwitch[((UIComboBox)sender).Name].Active = false;

            int index = ((UIComboBox)sender).SelectedIndex;
            //if (serDesCommList[index].IsOpen == false)
            //{
            //    //UIMessageDialog.ShowWarningDialog(FindForm(), string.Format("CH347({0})未打开", index));
            //    return;
            //}
            if(index < 0 || index == 0xFFFFFFF)
            {
                return;
            }
            UIComboBox combox = (UIComboBox)sender;
            string serDesComm = usbToSerDesComm[combox.Name];
            SerDesComm devComm = serDesCommList[index];
            //devComm.OpenDevice(devComm.DevID);
            switch (serDesComm)
            {
                case "NLS9116A":
                    if(usbDeviceMeditorA != null)
                    {
                        usbDeviceMeditorA.NotifySerDesChanged(devComm);//改变USB Device
                    }                   
                    break;
                case "NLS9116B":
                    if (usbDeviceMeditorB != null)
                    {
                        usbDeviceMeditorB.NotifySerDesChanged(devComm);//改变USB Device
                    }
                    break;
                case "NLS9116C":
                    if (usbDeviceMeditorC != null)
                    {
                        usbDeviceMeditorC.NotifySerDesChanged(devComm);//改变USB Device
                    }
                    break;
                case "NLS9116D":
                    if (usbDeviceMeditorD != null)
                    {
                        usbDeviceMeditorD.NotifySerDesChanged(devComm);//改变USB Device
                    }
                    break;
                case "NLS9246":
                    if (usbDeviceMeditorDes != null)
                    {
                        usbDeviceMeditorDes.NotifySerDesChanged(devComm);//改变USB Device
                    }
                    break;
                default:
                    break;

            }
            byte mask = 1 << 2;
            int flashCount = 3;

            if(index >= serDesCommList.Count) { return; }
            if (serDesCommList[index].IsOpen)
            {
                object lockObject = new object(); // 在循环外部创建一个锁对象
                lock (lockObject)
                {
                    serDesCommList[index].OpenDevice(index);
                }
                await Task.Run(async () =>
                {
                    {
                        while (flashCount-- > 0)
                        {
                            lock (lockObject)
                            {
                                serDesCommList[index].GPIO_Set(mask, mask);  // LED OFF
                            }
                            
                            await Task.Delay(500);
                            lock (lockObject)
                            {
                                serDesCommList[index].GPIO_Set(mask, 0);     // LED ON
                            }                           
                            await Task.Delay(500);
                        }
                    }
                });
            }
                
            else
            {
                UIMessageDialog.ShowErrorDialog(FindForm(), "CH347端口未打开!!!");
            }
            
            OnSetAddr?.Invoke(addToSerDesComm[DevToAddr[(UIComboBox)sender].Name], DevToAddr[(UIComboBox)sender].SelectedText);
        }

        public void RefreshComboxDevAndIICMode()
        {
            combox_dev_SelectedIndexChanged(combox_devA, null);
            combox_dev_SelectedIndexChanged(combox_devB, null);
            combox_dev_SelectedIndexChanged(combox_devC, null);
            combox_dev_SelectedIndexChanged(combox_devD, null);
            combox_dev_SelectedIndexChanged(combox_devDes, null);
            combox_IIC_Mode_selectedIndexChanged(combox_IICModeA, null);
            combox_IIC_Mode_selectedIndexChanged(combox_IICModeB, null);
            combox_IIC_Mode_selectedIndexChanged(combox_IICModeC, null);
            combox_IIC_Mode_selectedIndexChanged(combox_IICModeD, null);
            combox_IIC_Mode_selectedIndexChanged(combox_IICModeDes, null);
        }
        public delegate bool setAddr(string serDesComm,string add);

        public event setAddr OnSetAddr;

        private Dictionary<string, string> addToSerDesComm = new Dictionary<string, string>
        {
            {"combox_addA","NLS9116A" },
            {"combox_addB","NLS9116B" },
            {"combox_addC","NLS9116C" },
            {"combox_addD","NLS9116D" },
            {"combox_addDes","NLS9246" }
        };
        private Dictionary<string, string> usbToSerDesComm = new Dictionary<string, string>
        {
            {"combox_devA","NLS9116A" },
            {"combox_devB","NLS9116B" },
            {"combox_devC","NLS9116C" },
            {"combox_devD","NLS9116D" },
            {"combox_devDes","NLS9246" }
        };
        
        private void combox_add_selectedIndexChanged(object sender, EventArgs e)
        {
            UIComboBox combox = (UIComboBox)sender;
            string serDesComm = addToSerDesComm[combox.Name];
            string add = combox.SelectedText;
            OnSetAddr?.Invoke(serDesComm, add);
            switch (serDesComm)
            {
                case "NLS9116A":
                    mediatorA?.NotifyAddrssChanged(add);//改变Chip Address
                    break;
                case "NLS9116B":
                    mediatorB?.NotifyAddrssChanged(add);
                    break;
                case "NLS9116C":
                    mediatorC?.NotifyAddrssChanged(add);
                    break;
                case "NLS9116D":
                    mediatorD?.NotifyAddrssChanged(add);
                    break;
                case "NLS9246":
                    mediatorDes?.NotifyAddrssChanged(add);
                    break;
                default:
                    break;

            }
            
        }

        public AddressMeditor MediatorA
        {
            get { return mediatorA; }
            set { mediatorA = value; }
        }
        public AddressMeditor MediatorB
        {
            get { return mediatorB; }
            set { mediatorB = value; }
        }
        public AddressMeditor MediatorC
        {
            get { return mediatorC; }
            set { mediatorC = value; }
        }
        public AddressMeditor MediatorD
        {
            get { return mediatorD; }
            set { mediatorD = value; }
        }
        public AddressMeditor MediatorDes
        {
            get { return mediatorDes; }
            set { mediatorDes = value; }
        }

        public USBDeviceMeditor UsbDeviceMetorA
        {
            get { return usbDeviceMeditorA; }
            set { usbDeviceMeditorA = value; }
        }
        public USBDeviceMeditor UsbDeviceMetorB
        {
            get { return usbDeviceMeditorB; }
            set { usbDeviceMeditorB = value; }
        }
        public USBDeviceMeditor UsbDeviceMetorC
        {
            get { return usbDeviceMeditorC; }
            set { usbDeviceMeditorC = value; }
        }
        public USBDeviceMeditor UsbDeviceMetorD
        {
            get { return usbDeviceMeditorD; }
            set { usbDeviceMeditorD = value; }
        }
        public USBDeviceMeditor UsbDeviceMetorDes
        {
            get { return usbDeviceMeditorDes; }
            set { usbDeviceMeditorDes = value; }
        }

        //private string StateFileName = Application.StartupPath + "config_state.xml";
        //private string StateFileName = System.IO.Path.Combine(Application.StartupPath, "config_state.xml");

        public void SaveConfigState(string StateFileName,ConfigState config)
        {

            config.ComboxAddAIndex = this.combox_addA.SelectedIndex;
            config.ComboxAddBIndex = this.combox_addB.SelectedIndex;
            config.ComboxAddCIndex = this.combox_addC.SelectedIndex;
            config.ComboxAddDIndex = this.combox_addD.SelectedIndex;
            config.ComboxAddDesIndex = this.combox_addDes.SelectedIndex;
            config.ComboxDevAIndex = this.combox_devA.SelectedIndex;
            config.ComboxDevBIndex = this.combox_devB.SelectedIndex;
            config.ComboxDevCIndex = this.combox_devC.SelectedIndex;
            config.ComboxDevDIndex = this.combox_devD.SelectedIndex;
            config.ComboxDevDesIndex = this.combox_devDes.SelectedIndex;
            config.SwitchA = this.uiSwitchA.Active;
            config.SwitchB = this.uiSwitchB.Active;
            config.SwitchC = this.uiSwitchC.Active;
            config.SwitchD = this.uiSwitchD.Active;
            config.SwitchDes = this.uiSwitchDes.Active;

            //XmlSerializer serializer = new XmlSerializer(typeof(ConfigState));
            //using(FileStream fs = new FileStream(StateFileName, FileMode.Create))
            //{
            //    serializer.Serialize(fs, config);
            //}

        }

        public void LoadConfigState(string StateFileName,ConfigState state) 
        {
            //if(File.Exists(StateFileName))
            //{
            //    XmlSerializer serializer = new XmlSerializer(typeof(ConfigState));
            //    using (FileStream fs = new FileStream(StateFileName, FileMode.Open))
            //    {
                    combox_addA.SelectedIndex = state.ComboxAddAIndex;
                    combox_addB.SelectedIndex = state.ComboxAddBIndex;
                    combox_addC.SelectedIndex = state.ComboxAddCIndex;
                    combox_addD.SelectedIndex = state.ComboxAddDIndex;
                    combox_addDes.SelectedIndex = state.ComboxAddDesIndex;
                    combox_devA.SelectedIndex = state.ComboxDevAIndex;
                    combox_devB.SelectedIndex = state.ComboxDevBIndex;
                    combox_devC.SelectedIndex = state.ComboxDevCIndex;
                    combox_devD.SelectedIndex = state.ComboxDevDIndex;
                    combox_devDes.SelectedIndex = state.ComboxDevDesIndex;

                    uiSwitchA.Active = state.SwitchA;
                    uiSwitchB.Active = state.SwitchB;
                    uiSwitchC.Active = state.SwitchC;
                    uiSwitchD.Active = state.SwitchD;
                    uiSwitchDes.Active = state.SwitchDes;
            //    }
            //}
        }       

        private void combox_IIC_Mode_selectedIndexChanged(object sender, EventArgs e)
        {
            UIComboBox combox_IICMode = sender as UIComboBox;
            if(combox_IICMode != null && combox_IICMode.SelectedIndex != -1)
            {
                if(combox_IICMode == combox_IICModeA && combox_devA.SelectedIndex != -1)
                {
                    serDesCommList[combox_devA.SelectedIndex].IIC_Mode_Set((uint)combox_IICMode.SelectedIndex, 0);
                }
                else if (combox_IICMode == combox_IICModeB && combox_devB.SelectedIndex != -1)
                {
                    serDesCommList[combox_devB.SelectedIndex].IIC_Mode_Set((uint)combox_IICMode.SelectedIndex, 0);
                }
                else if (combox_IICMode == combox_IICModeC && combox_devC.SelectedIndex != -1)
                {
                     serDesCommList[combox_devC.SelectedIndex].IIC_Mode_Set((uint)combox_IICMode.SelectedIndex, 0);
                }
                else if (combox_IICMode == combox_IICModeD && combox_devD.SelectedIndex != -1)
                {
                    serDesCommList[combox_devB.SelectedIndex].IIC_Mode_Set((uint)combox_IICMode.SelectedIndex, 0);
                }
                else if (combox_IICMode == combox_IICModeDes && combox_devDes.SelectedIndex != -1)
                {
                    serDesCommList[combox_devDes.SelectedIndex].IIC_Mode_Set((uint)combox_IICMode.SelectedIndex, 0);
                }
            }
        }


    }
}